Guava常用写法
Overview
最近由于项目很多还是使用jdk1.7 没有java8的stream等遍历集合的API。但是有看到老师用了guava中遍历集合的方法,知道了guava这个强大的工具包。发现java8很多东西都是抽象或者风格模仿自guava。这里总结一些常用的写法。在写代码时可以提高效率。不求一次能总结,慢慢的总结吧。
List处理
- 需求:数据库模型Entity转交互Data时,两个结构相似。在java8中我们stream后直接collection就好。但是guava有个类似写法:
List<Data> dataList = Lists.transform(entityList, new Function<Entity, Data>() { @Nullable @Override public Data apply(@Nullable Entity input) { ..... Entity ---> Data; } }).toList();
- 生成一个List, 带有数据
同时可以初始化100的listList<Data> list = Lists.newArrayList(data1,data2...); //Lists.newLinkedList();
List<Data> list = Lists.newArrayListWithCapacity(100);
- 把一个list拆分子list
//把allList拆分为每个3个成员的子list。最后一个可能小于3个成员 List<List<Long>> list = Lists.partition(allList, 3);
- 返回一个队列倒序队列
List<Data> list = Lists.reverse(originalList);
- 返回一个并发写队列。队列在迭代时不能写入。
List<Data> list = Lists.newCopyOnWriteArrayList();
不可变List。
- 对不可靠的客户代码库来说,它使用安全,可以在未受信任的类库中安全的使用这些对象
- 线程安全的:immutable对象在多线程下安全,没有竞态条件
- 不需要支持可变性, 可以尽量节省空间和时间的开销. 所有的不可变集合实现都比可变集合更加有效的利用内存 (analysis)
- 可以被使用为一个常量,并且期望在未来也是保持不变的
创建不可变list:
List<Person> immutableList = ImmutableList.of(new Person("chenhao2", 23),new Person("chenhao2", 24)); List<Person> immutableList1 = ImmutableList.<Person>builder().add(new Person("chenhao2", 23),new Person("chenhao2", 24)).build(); List<Person> immutableList2 = ImmutableList.copyOf(persons);
FluentIterable
流试迭代
package com.yy.apollo.demo;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import lombok.Data;
public class FluentIterableTest {
public static void main(String[] args) {
//创建一个队列
List<Person> persons = Lists.newArrayList(
new Person("chenhao2", 23),
new Person("chenhao3", 30),
new Person("chenhao4", 40),
new Person("chenhao5", 50),
new Person("chenhao6", 60),
new Person("chenhao7", 70),
new Person("chenhao100", 100));
FluentIterable.from(
//从Person-->User 队列
Lists.transform(persons, new Function<Person, User>() {
@Override
public User apply(Person input) {
return new User(input);
}
}))
//过滤User age>70的User
.filter(new Predicate<User>() {
@Override
public boolean apply(User input) {
if (input.getAge() > 70) {
return false;
}
return true;
}
})
//截取前4个
.limit(4)
//跳过第一个
.skip(1)
//循环遍历剩下的
.forEach(action -> {
System.out.println(action);
});
}
}
@Data
class Person {
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
private String name;
private int age;
}
@Data
class User {
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
public User(Person person) {
this.name = person.getName();
this.age = person.getAge();
}
private String name;
private int age;
}
FluentIterable 提供了很多方法。如:
- from:从Iterable 生成FluentIterable
- concat: 拼接
- append: 添加
- filter: 过滤器
- anyMatch: 返回boolean是否有任何匹配到
- allMatch: 返回boolean是否全部匹配到
- transform: 先转化再匹配
- toList: 收集为队列
- toSet: 收集成set
- toSortedList 收集为排序队列
- toSortedSet 收集为排序set
- toMap 收集为Map
等。
Map处理
- 各种Map创建
// 创建hashmap Map<String, Object> hashmap = Maps.newHashMap(); // 创建map固定长度 Map<String, Object> hashmap2 = Maps.newHashMapWithExpectedSize(10); // 创建IdentityHashMap。IdentityHashMap判定相同是key1==key2严格的map Map<String, Object> hashmap3 = Maps.newIdentityHashMap(); // 保持顺序的hashMap,额外维持一个顺序链表。 Map<String, Object> hashmap4 = Maps.newLinkedHashMap();
- Map value值对象定向转换,
// Map中设计的元素value改变。比如从Map<String,Person>改变为Map<String,User> Map<String, Person> fromMap = ImmutableMap.of("user1", new Person("chen", 19), "user2",new Person("chen1", 22)); Map<String, User> toMap = Maps.transformValues(fromMap, new Function<Person, User>() { @Override public User apply(Person input) { return new User(input); } });
- 根据key和value生成一个新Map
Map<String, User> toMap2 = Maps.transformEntries(fromMap, new EntryTransformer<String, Person, User>() { @Override public User transformEntry(String key, Person value) { return new User(value); } });
- 根据entry过滤
Map<String, Person> toMap3 = Maps.filterEntries(fromMap, new Predicate<Entry<String, Person>>() { @Override public boolean apply(Entry<String, Person> input) { return false; } });
- list,set转Map。Key为List元素处理而来。
List<Person> inList = Lists.newArrayList(new Person("111", 22),new Person("222", 222)); Map<String, Person> map4 = Maps.uniqueIndex(inList, new Function<Person,String>(){ @Override public String apply(Person input) { return input.getName(); } });
- set转map,set值做Key
Set<Person> set = Sets.newHashSet(new Person("111", 22),new Person("222", 222)); Map<Person, String> map5 = Maps.asMap(set, new Function<Person,String>(){ @Override public String apply(Person input) { return null; } });
Joiner,Splitter
* list转换为字符串
*/
@Test
public void joinTest(){
List<String> names = Lists.newArrayList("John", "Jane", "Adam", "Tom");
String result = Joiner.on(",").join(names);
assertEquals(result, "John,Jane,Adam,Tom");
}
/**
* map转换为字符串
*/
@Test
public void whenConvertMapToString_thenConverted() {
Map<String, Integer> salary = Maps.newHashMap();
salary.put("John", 1000);
salary.put("Jane", 1500);
String result = Joiner.on(" , ").withKeyValueSeparator(" = ")
.join(salary);
System.out.println(result);
}
/**
* list转String,跳过null
*/
@Test
public void whenConvertListToStringAndSkipNull_thenConverted() {
List<String> names = Lists.newArrayList("John", null, "Jane", "Adam", "Tom");
String result = Joiner.on(",").skipNulls().join(names);
System.out.println(result);
assertEquals(result, "John,Jane,Adam,Tom");
}
/**
* list转String,将null变成其他值
*/
@Test
public void whenUseForNull_thenUsed() {
List<String> names = Lists.newArrayList("John", null, "Jane", "Adam", "Tom");
String result = Joiner.on(",").useForNull("nameless").join(names);
System.out.println(result);
assertEquals(result, "John,nameless,Jane,Adam,Tom");
}
/**
* String to List
*/
@Test
public void whenCreateListFromString_thenCreated() {
String input = "apple - banana - orange";
List<String> result = Splitter.on("-").trimResults().splitToList(input);
System.out.println(result);
//assertThat(result, contains("apple", "banana", "orange"));
}
/**
* String to Map
*/
@Test
public void whenCreateMapFromString_thenCreated() {
String input = "John=first,Adam=second";
Map<String, String> result = Splitter.on(",")
.withKeyValueSeparator("=")
.split(input);
assertEquals("first", result.get("John"));
assertEquals("second", result.get("Adam"));
}
/**
* 多个字符进行分割
*/
@Test
public void whenSplitStringOnMultipleSeparator_thenSplit() {
String input = "apple.banana,,orange,,.";
List<String> result = Splitter.onPattern("[.|,]")
.omitEmptyStrings()
.splitToList(input);
System.out.println(result);
}
/**
* 每隔多少字符进行分割
*/
@Test
public void whenSplitStringOnSpecificLength_thenSplit() {
String input = "Hello world";
List<String> result = Splitter.fixedLength(3).splitToList(input);
System.out.println(result);
}
/**
* 限制分割多少字后停止
*/
@Test
public void whenLimitSplitting_thenLimited() {
String input = "a,b,c,d,e";
List<String> result = Splitter.on(",")
.limit(4)
.splitToList(input);
assertEquals(4, result.size());
System.out.println(result);
}
Cache
关于guava的cache,从spring 5开始就不再支持了,改用caffeine。但是这里还是写一下吧。caffeine是基于java8的,java8以下还是只能用guava。官方号称caffeine比guava的cache快。不过caffeine的风格基本照搬guava的cache
private LoadingCache<String, List<User>> userCache = CacheBuilder.newBuilder()
//过期时间
.expireAfterWrite(5, SECONDS)
//最大长度
.maximumSize(10).build(new CacheLoader<String, List<User>>() {
@Override
public List<User> load(String key) throws Exception {
....进行BD查询返回操作等
}
});
如果想定时刷新,使用执行器加重写reload方法
private LoadingCache<String, List<User>> userCache = CacheBuilder.newBuilder()
//过期时间
.expireAfterWrite(5, SECONDS)
//最大长度
.maximumSize(10).build(new CacheLoader<String, List<User>>() {
@Override
public List<User> load(String key) throws Exception {
....进行BD查询返回操作等
}
@Override
public ListenableFuture<List<User>> reload(String key, final List<User> oldValue)
throws Exception {
return EXECUTOR.submit(() -> {
List<User> list = doFindUser();
});
}
});
//再加个定时器
@PostConstruct
public void init() throws Exception {
// 定时刷新 5秒
EXECUTOR.scheduleWithFixedDelay(() -> USER_CACHE.refresh(StringUtils.EMPTY), 3, 5, TimeUnit.SECONDS);
// 预加载
doFindUser();
}
或者使用
@PostConstruct
private void init() {
refresh();
}
@Scheduled(fixedDelay = 30_000, initialDelay = 5_000)
private void refresh() {
USER_CACHE.refresh(StringUtils.EMPTY);
}